package com.dmy.component;

import com.dmy.config.GlobleConfig;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.geom.Point2D;
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

public  class Letter {

    private static final char c[] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

    private static final int sd = 2;
    private static int lineHeght= 0;
    private static int delay = 200;

    private long zq = 0;
    private long keyN = 0;
    private ZB zbs[]; // 默认的字母存储容器
    private JComponent jComponent;


    public Letter(JComponent jComponent,int len){
        this.jComponent = jComponent;
        zbs = new ZB[len];
        _init(GlobleConfig.WINDOW_HRIGHT);
        CompletableFuture.runAsync(()->{
            long timeout = 0;
            while (true) {
                try {
                    Thread.sleep(delay);
                    if(System.currentTimeMillis()>=timeout&&delay>30){
                        timeout = System.currentTimeMillis()+400;
                        delay = delay>30?--delay:delay;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(((MJPanel)jComponent).getTolerance()<=0){
                    break;
                }
                for (int i = 0; i < zbs.length; i++) {
                    final int Final_i = i;
                    Optional.ofNullable(zbs[i]).ifPresent(z -> {
                        if (z.y > GlobleConfig.WINDOW_HRIGHT) {
                            zbs[Final_i] = null;
                            ((MJPanel)jComponent).reduction();
                        } else {
                            z.y += sd;
                        }
                        _init(GlobleConfig.WINDOW_HRIGHT / 2);
                        jComponent.repaint();
                    });
                }
            }
            JOptionPane.showMessageDialog(null,"你死了！！！");

        });
        CompletableFuture.completedFuture(this)
                .thenAcceptAsync(t->{
                    while (true){
                        try {
                            TimeUnit.MILLISECONDS.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if(Letter.lineHeght < GlobleConfig.WINDOW_HRIGHT-200){
                            t.lineHeght++;
                        }else{
                            break;
                        }
                        jComponent.repaint();
                    }
                });
    }

    public final Color getRandomColor(){
        return new Color(new Random().nextInt(200)+56,new Random().nextInt(200)+56,new Random().nextInt(200)+56);
    }

    private final void _init(int hash) {
        for (int i = 0; i < zbs.length; i++) {
            if(zbs[i]==null){
                zbs[i]=new ZB(new Random().nextInt(GlobleConfig.WINDOW_WIDTH-50)+10,-new Random().nextInt(hash),c[new Random().nextInt(c.length)],System.currentTimeMillis(),getRandomColor()) ;
            }
        }
    }


    public void clearOf(char c) {
        final char cc = Character.toUpperCase(c);
        Stream<ZB> stream = Arrays.stream(zbs).filter(i -> i!=null && i.c == cc);
        Optional<ZB> max = stream.max((c1, c2) -> c1.y - c2.y);
        ZB zb = max.orElse(null);
        if (zb==null||zb.y<lineHeght+20){
            return;
        }
        for (int i = 0; i < zbs.length; i++) {
            if(zbs[i]!=null && zbs[i]==zb){
                zbs[i]=null;
                this.zq++;
            }
        }
    }

    public void paint(Graphics2D g) {

        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.3f));
        g.setColor(Color.MAGENTA);
        g.fillRect(0,0,GlobleConfig.WINDOW_WIDTH,Letter.lineHeght);

        g.setPaint(new GradientPaint(0,GlobleConfig.WINDOW_WIDTH/2,Color.CYAN,GlobleConfig.WINDOW_WIDTH/2,GlobleConfig.WINDOW_WIDTH,Color.LIGHT_GRAY));
        g.drawLine(0,lineHeght,GlobleConfig.WINDOW_WIDTH,lineHeght);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        for (ZB zb : zbs) {
            Optional.ofNullable(zb).ifPresent(z->{
                g.setColor(z.color);
                g.setFont(new Font("楷体",Font.BOLD,30));
                g.drawString(String.valueOf(z.c),z.x,z.y);
            });
        }
    }

    public void keyPressed() {
        this.keyN++;
    }

    public String getCorrect() {
        return String.valueOf((int)(zq*1.0/keyN*100))+" %";
    }

    // 每个字母的表示
    private static class ZB{

        private String uuid;
        private int x;
        private int y;
        private char c;
        private long time;
        private Color color;

        public ZB() {
        }

        public ZB(int x, int y, char c, long time, Color color) {
            this.x = x;
            this.y = y;
            this.c = c;
            this.time = time;
            this.color = color;
            this.uuid = UUID.randomUUID().toString();
        }

        @Override
        public String toString() {
            return "ZB{" +
                    "uuid='" + uuid + '\'' +
                    ", x=" + x +
                    ", y=" + y +
                    ", c=" + c +
                    ", time=" + time +
                    ", color=" + color +
                    '}';
        }

        public String getUuid() {
            return uuid;
        }

        public void setUuid(String uuid) {
            this.uuid = uuid;
        }


        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        public char getC() {
            return c;
        }

        public void setC(char c) {
            this.c = c;
        }

        public long getTime() {
            return time;
        }

        public void setTime(long time) {
            this.time = time;
        }

        public Color getColor() {
            return color;
        }

        public void setColor(Color color) {
            this.color = color;
        }
    }

}
